package com.file.manage.infrastructure.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.json.JSONUtil;
import com.file.manage.domain.enums.UserRole;
import com.file.manage.infrastructure.base.CommonResult;
import com.file.manage.infrastructure.base.ResultCode;
import io.swagger.v3.core.util.Json;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * sa-token的全局配置
 *
 * @author H41
 */
@Configuration
@Slf4j
public class SaTokenConfigure implements WebMvcConfigurer {

    //白名单：无需登录即可访问的接口地址
    private static final String[] WHITE_LIST = {
            "/auth/**",
            "/file/downLoadFile/**",
            "/swagger-ui.html",
            "/swagger-resources/**",
            "/webjars/**",
            "/v2/api-docs",
            "/v2/api-docs/**",
            "/v3/api-docs",
            "/v3/api-docs/**",
            "/doc.html",
            "/doc.html/**",
            "/doc.html#/**",
            "/webjars/springfox-swagger-ui/**",
            "/file/downLoadFile/**",
    };

    // 注册 Sa-Token 拦截器，打开注解式鉴权功能
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 拦截器，打开注解式鉴权功能
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
    }

    @Bean
    public SaServletFilter getSaServletFilter() {
        return new SaServletFilter()
                // 拦截地址
                .addInclude("/**")
                // 开放地址
                .addExclude("/favicon.ico")
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    // 登录校验 -- 拦截所有路由
                    SaRouter.match("/**").notMatch(WHITE_LIST).check(r -> StpUtil.checkLogin());

                    // 权限认证 -- 不同模块, 校验不同权限
//                    SaRouter.match("/admin/**", r -> StpUtil.checkRole(UserRole.ADMIN.name()));
//                    SaRouter.match("/trade/**", r -> StpUtil.checkPermission(UserPermission.AUTH.name()));
//
//                    SaRouter.match("/user/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(), UserPermission.FROZEN.name()));
//                    SaRouter.match("/order/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(),UserPermission.FROZEN.name()));
                })
                // 异常处理方法：每次setAuth函数出现异常时进入
                .setError(this::getSaResult)
// 前置函数：在每次认证函数之前执行
                .setBeforeAuth(obj -> {
                    // ---------- 设置跨域响应头 ----------
                    SaHolder.getResponse()
                            // 允许指定域访问跨域资源
                            .setHeader("Access-Control-Allow-Origin", "*")
                            // 允许所有请求方式
                            .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
                            // 有效时间
                            .setHeader("Access-Control-Max-Age", "36000")
                            // 允许的header参数
                            .setHeader("Access-Control-Allow-Headers", "*");
                    ;
                    // 异常处理方法：每次setAuth函数出现异常时进入;
                });
    }

    private String getSaResult(Throwable throwable) {
        switch (throwable) {
            case NotLoginException notLoginException:
                log.error("请先登录");
                return JSONUtil.toJsonStr(CommonResult.failed(ResultCode.NOT_LOGIN));
            case NotRoleException notRoleException:
                if (UserRole.ADMIN.name().equals(notRoleException.getRole())) {
                    log.error("请勿越权使用！");
                    return JSONUtil.toJsonStr(CommonResult.failed("请勿越权使用！"));
                }
                log.error("您无权限进行此操作！");
                return JSONUtil.toJsonStr(CommonResult.failed(ResultCode.NOT_PERMISSION));
            case NotPermissionException notPermissionException:
                log.error("您无权限进行此操作！");
                return JSONUtil.toJsonStr(CommonResult.failed(ResultCode.NOT_PERMISSION));
            default:
                return JSONUtil.toJsonStr(CommonResult.failed(throwable.getMessage()));
        }
    }
}
